/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
module dwt.widgets.runnablelock;


private import dwt.dwt;

private import dwt.util.javatypes;
private import dwt.util.util;


/**
 * <Shawn Liu> since D don't have a machnism like java Object.wait() Object.notify()
 * do it myself
 */

private import dwt.internal.win32.os;


/**
 * Instances of this class are used to ensure that an
 * application cannot interfere with the locking mechanism
 * used to implement asynchonous and synchronous communication
 * between widgets and background threads.
 */
// <shawn>, not a public class

package class RunnableLock {

	private import tango.core.Thread;
	
	boolean useDelegate = false;
	void delegate(Object args) func;
	Object cData; // custom data
	
	Runnable runnable;
	Thread thread;
	Exception throwable;
	
	private HANDLE hEvent = null;
	
this (Runnable runnable) {
	this.runnable = runnable;
}


this (Object customData, void delegate(Object) func) {
	this.func = func;
	useDelegate = true;
	cData = customData;
} 

~ this() {
	dispose();
}

void dispose() {
	if(hEvent){
		OS.CloseHandle(hEvent);
		hEvent = null;
	}
}

boolean done () {
	if(useDelegate)
		return func is null || throwable !is null;	
	return runnable is null || throwable !is null;
}

void run () {
	if(useDelegate){
		if (func !is null) func(cData);
		func = null;
	}else{
		if (runnable !is null) runnable.run ();
		runnable = null;
	}
}

package void wait(){
	if(hEvent is null){
		hEvent = OS.CreateEvent(null, false, false, null);
	}
	if(hEvent is null)
		throw new Exception("Failed to create wait event");
	
	OS.WaitForSingleObject(hEvent, OS.INFINITE); 
}

package void notifyAll() {
	if(hEvent){
		OS.SetEvent(hEvent);
	}
}

}
